<?php
require('GifMerge.class.php');
/*//////////////////////////////////////////////////////*/
/*//                                                  //*/
/*//     Y A X I S R O T A T E . C L A S S . P H P    //*/
/*//                                                  //*/
/*//////////////////////////////////////////////////////*/
/*
            YAxisRotate V 1.0e (C) http://wwww.cyber8.net 
   =======================================================
   Can be used for freeware or commercial services,
   can be distributed anywhere but cannot be modified sourcecode
   without permission of author.
   If you use this class please refer with a link to me.
   =======================================================
         Constructor:
         *YAxisRotate(array A_IMAGES, int T_SPACING, int T_FRAMES_PER_TURN,
                         int F_DELAY, int F_PAUSE, int A_WIDTH, array A_HEIGHT, 
                        bool A_REFLECT, bool A_BORDER, int A_ANGLE, bool B_DITHER, 
                        int F_RESIZE, bool F_SAVEFRAMES) 
*/
class News_UI_YAxisRotate
{
    var $pictures = array();
    var $objects  = array();
    var $spacing;
    var $frames_per_turn;
    var $delay;
    var $pause;
    var $palette_width;
    var $palette_height;
    var $use_reflection;
    var $border_color;
    var $bg_color;
    var $angle;
    var $dither;
    var $debug;
    var $resize;
    var $saveframes;
    var $bgcolor;
    var $savepath;
    var $process_as_jpeg;


#Private
    var $frame;
    var $sx;
    var $sy;
    var $white;
    var $black;
    var $green;
    var $red;
    var $gray; 
    var $palette_y_axis;
    var $palette_x_axis;
    var $img_midpt_right;
    var $img_midpt_left;
    var $img_midpt_top; 
    var $height_left;
    var $height_right;
    var $current_width;
    var $left_top;
    var $right_top;
    var $top_left; 
    var $left_bottom;
    var $right_bottom;
    var $top_right;
    var $decrease;
    var $framecount;
    var $right_turn_flag;
    var $left_turn_flag;
    var $turn_index;
    var $top_line;
    var $left_line;
    var $bottom_line;
    var $right_line;
    var $plumb_line;
    var $image_height;
    var $image_width;
    var $border;
    var $singleframe;
    var $frame_index;
      
    function News_UI_YAxisRotate($pictures=NULL, # YAxisRotate
                         $spacing=1,
                         $frames_per_turn=10,
                         $delay=16,
                         $pause=16,
                         $palette_width=640,
                         $palette_height=480,
                         $use_reflection=NULL,
                         $border_color=0x990000,
                         $bg_color=0xFFFFFF,
                         $angle=NULL,
                         $dither=NULL,
                         $resize=NULL,
                         $saveframes=NULL,
                         $savepath=".")
    { 
        $this->pictures           = $pictures;
        $this->spacing            = $spacing;
        $this->frames_per_turn    = $frames_per_turn;
        $this->delay              = $delay;
        $this->pause              = $pause;
        $this->palette_width      = $palette_width;
        $this->palette_height     = $palette_height;
        $this->use_reflection     = $use_reflection;
        $this->border_color       = $border_color;
        $this->bg_color           = $bg_color;
        $this->angle              = $angle;
        $this->dither             = $dither;
        $this->debug              = $debug;
        $this->resize             = $resize;
        $this->saveframes         = $saveframes;
        $this->savepath           = $savepath;
    } # YAxisRotate

# ----------------------------------------------------------------------------
    
    function create($flat=-1) # create
    {
        header('Content-type: image/gif'); 
        $this->draw_2d($flat);
    } # create

# ----------------------------------------------------------------------------

    function draw_2d($flat=-1) # draw_2d
    { 
        $__i=array();
        $__d=array();
        $__x=array();
        $__y=array(); 
          
        $this->open(); 
        
        # begin frames
        for ($this->frame_index=0;$this->frame_index<$this->framecount;$this->frame_index++)
        { 
            $this->generate_workspace();   
            
            $this->scan(); 
            
			
			if ($this->process_as_jpeg)
			{
				ob_start();
				imagejpeg($this->frame); 
				$mem = ob_get_contents();
				$this->frame = imagecreatefromstring ($mem);
				ob_end_clean();  
			}
			
			ob_start();
			imagegif($this->frame); 
			$__i[] = ob_get_contents();
			ob_end_clean();
 
            $__x[] = 0;
            $__y[] = 0; 
            $__d[] = $this->frame_index % $this->frames_per_turn==0 ? $this->pause : $this->delay;  
            
            $this->increment();
            
            if ($this->singleframe && $this->singleframe==$this->frame_index+1)
            { 
                imagegif($this->frame);
                exit; 
            }
        } 
        
		if ($flat>=0)
		{
			echo $__i[$flat];
			exit;
		}
		
        $gifmerge    = new GifMerge($__i, 1, 1, 1, -10, $__d, 2, $__x, $__y, 'C_MEMORY');
        echo $gifmerge -> getAnimation();    
    } # draw_2d

# ----------------------------------------------------------------------------
    
    function open() # open
    {
        foreach ($this->pictures as $picture)
        {
            $this_image = @imagecreatefromjpeg($picture); 
            if ($this_image)
            {
                list($this->image_width, $this->image_height, $type, $attr) = getimagesize($picture); 
                if ($this->resize)
                { # resize images where specified
                    $tmp_r                    = $this->image_width / $this->image_height; 
                    $tmp_h                    = $this->resize / $tmp_r; 
                    $tmp_img                  = imagecreatetruecolor ($this->resize, $tmp_h);
                    
                    imagecopyresampled($tmp_img, $this_image, 0, 0, 0, 0, $this->resize, $tmp_h, $this->image_width, $this->image_height);   
                    
                    $this_image              = $tmp_img;
                    $this->image_width       = $this->resize;
                    $this->image_height      = $tmp_h;
                }   
                $this->objects[] = $this_image;
            }
        }  
		
        $this->turntable = array(); 
        $this->turntable[]=0; 
        for ($e=1;$e<count($this->objects);$e++)
        {
            $this->turntable[] = $e;
            $this->turntable[] = $e;
        }
        $this->turntable[]=0;  
          
        $this->decrease        = $this->image_width / $this->frames_per_turn;
        $this->framecount      = $this->frames_per_turn * count($this->objects); 
        $this->right_turn_flag = -1;
        $this->left_turn_flag  = 1;
        $this->turn_index      = 0;  
        $this->current_width   = $this->image_width;
        $this->height_left     = $this->image_height;
        $this->height_right    = $this->image_height; 
		$this->plumb_line      = NULL;
    } # open

# ----------------------------------------------------------------------------
    
    function scan() # scan
    {    
        if ($this->angle)
        {
            $this->scan_angled();
        }
        else
        {
            $this->scan_upright();
        }    
        if ($this->border_color)
        {
            imagepolygon($this->frame, $this->border, 4, $this->border_color); 
        }   
        $this->debug();
    }
	
# ----------------------------------------------------------------------------
    
	function drawgrid() # drawgrid
	{
		if ($this->debug)
		{
			for ($ve=10;$ve<$this->sx;$ve+=10)
			{ # draw grid lines
				imageline ($this->frame, $ve, 0,$ve, $this->sy, $this->ltgreen); 
			}
			for ($ve=10;$ve<$this->sy;$ve+=10)
			{ # draw grid lines 
				imageline ($this->frame,0, $ve ,$this->sx, $ve , $this->ltgreen);
			}
        }
	} # drawgrid
	
# ----------------------------------------------------------------------------
    
    function save() # save
    {   
        if ($this->saveframes)
        {
            $name = $this->savepath . "/_frame" . $this->frame_index . ".jpg";
            imagepng ($this->frame, $name); 
        }  
    } # save

# ----------------------------------------------------------------------------
    
    function debug() # debug
    {   
		if ($this->debug)
		{
			imagestring ($this->frame,2,10,10,"Frame " . $this->frame_index ,$this->red);
			imagestring ($this->frame,2,10,20,"Turn " . $this->turn_index ,$this->red);
			imagestring ($this->frame,2,10,30,"Time " . date("H:i:s") ,$this->red);
			imagestring ($this->frame,2,10,40,"File " . $this->pictures[ $this->turntable[$this->turn_index] ] ,$this->blue);
			
			
			if ($this->angle)
			{
			    imagestring ($this->frame,2,$this->top_line->x_1-70,$this->top_line->y_1-70,round($this->top_line->x_1,2).", ". round($this->top_line->y_1,2), $this->green);
			    imageline ($this->frame,$this->top_line->x_1-60,$this->top_line->y_1-60,$this->top_line->x_1,$this->top_line->y_1, $this->green);
				
			    imagestring ($this->frame,2,$this->top_line->x_2+70,$this->top_line->y_2-70,round($this->top_line->x_2,2).", ". round($this->top_line->y_2,2), $this->red);
			    imageline ($this->frame,$this->top_line->x_2+60,$this->top_line->y_2-60,$this->top_line->x_2,$this->top_line->y_2, $this->red);
				
			    imagestring ($this->frame,2,$this->bottom_line->x_1+70,$this->bottom_line->y_1-70,round($this->bottom_line->x_1,2).", ". round($this->bottom_line->y_1,2), $this->black);
			    imageline ($this->frame,$this->bottom_line->x_1+60,$this->bottom_line->y_1-60,$this->bottom_line->x_1,$this->bottom_line->y_1, $this->black);
				
			    imagestring ($this->frame,2,$this->bottom_line->x_2-70,$this->bottom_line->y_2-70,round($this->bottom_line->x_2,2).", ". round($this->bottom_line->y_2,2), $this->blue);
			    imageline ($this->frame,$this->bottom_line->x_2-60,$this->bottom_line->y_2-60,$this->bottom_line->x_2,$this->bottom_line->y_2, $this->blue);
				
			}
			else
			{
				imagestring ($this->frame,2,$this->top_left,$this->left_top-14,"T1 $this->top_left,L1 $this->left_top",$this->red);
				imagestring ($this->frame,2,$this->top_right-50,$this->right_top-14,"T2 $this->top_right,R1 $this->right_top",$this->red);
				imagestring ($this->frame,2,$this->top_right-50,$this->right_bottom,"T2 $this->top_right,R2 $this->right_bottom",$this->red);
				imagestring ($this->frame,2,$this->top_left,$this->left_bottom,"T1 $this->top_left,L2 $this->left_bottom",$this->red);
			}
		}
    } # debug

# ----------------------------------------------------------------------------
    
    function scan_upright() # scan_upright
    {   
        # "scan" along the top line to derive all points along it
        # ========================================================================    
        $min_top = min($this->top_line->x_1, $this->top_line->x_2);
        $max_top = max($this->top_line->x_1, $this->top_line->x_2);
        $range   = $max_top - $min_top;  
        $ratio   = $range > 0 ? $this->image_width/$range : $range;  
        for ($x=$min_top;$x<=$max_top;$x+=$this->spacing)
        {
            # ROTATION
            # ========================================================================    
            $tick      = ($x - $min_top) * $ratio; 
            $top_y     = ($this->top_line->slope * $x) + $this->top_line->intercept;
            $bottom_y  = ($this->bottom_line->slope * $x) + $this->bottom_line->intercept;                         
            imagecopyresampled($this->frame, $this->objects[ $this->turntable[$this->turn_index] ], $x, $top_y, $tick, 0, 1, $bottom_y-$top_y, 1, $this->image_height);  
            # ========================================================================    
            
            # REFLECTION
            # ========================================================================    
            if($this->use_reflection)
            {                                                                                                                 
                $alpha = 1;                       
                $offset = $bottom_y + 1;                       
                for($y=$bottom_y;$y<=$this->sy;$y++)
                {
				    $this->reflect_pixel ($x, $offset--, $y, $alpha);                                                          
                    $alpha += 2;                                                                                                                             
                    if ($alpha > 100)                                                                                                                              
                    {                                                                                                                              
                        break;                                                                                                                              
                    }                                       
                }
            }     
        }  
    } # scan_upright

# ----------------------------------------------------------------------------
    
    function scan_angled() # scan_angled
    {     
        if ($this->top_line->length > 0 && $this->img_midpt_top > 0)
        {
            $image_to_surface = $this->image_width/ $this->top_line->length;   
            for ($point_x=0;$point_x<$this->top_line->length-1;$point_x++)
            {
                # find the corresponding X coord in the image
                $image_x_pt_top   = $point_x * $image_to_surface;   
                
                # get XY coords for this point
                $this_pt_top      = get_offset_from_angle ($point_x, $this->top_line->angle);
                $this_x_pt_top    = $this_pt_top->x + $this->top_line->x_1; # get current X coord  
                
                # find current Y coord based on X coord and the slope of the top line
                $this_y_pt_top    = ($this_x_pt_top * $this->top_line->slope) + $this->top_line->intercept;
                
                # $this_x_pt_top, $this_y_pt_top is the first point in the new "vertical" line   
                # get the y-intercept of the new "vertical" line  
                $this_y_intercept = $this_y_pt_top - ($this->left_line->slope * $this_x_pt_top);   
                
                # find intersection point with bottom line
                # eliminate X by normalizing the coefficients 
                $numerator        = ($this_y_intercept * $this->bottom_line->slope) - ($this->bottom_line->intercept * $this->left_line->slope);
                $denominator      = $this->bottom_line->slope - $this->left_line->slope; 
                if ($denominator!=0)
                {
                    # solve for Y in the intersection point
                    $this_y_pt_bottom = $numerator/$denominator;
                    
                    # solve for X in the intersection point
                    $this_x_pt_bottom = ($this_y_pt_bottom - $this_y_intercept) / $this->left_line->slope;
                    
                    # get the actual height of the line
                    $abs_x   = abs ($this_x_pt_bottom - $this_x_pt_top);
                    $abs_y   = abs ($this_y_pt_bottom - $this_y_pt_top); 
                    $abs_hgt = sqrt(pow ($abs_x,2) + pow ($abs_y,2));  
                     
                    # create a temp image of this height to copy onto the surface 
                    $temp_image_slice = @imagecreatetruecolor (1, $abs_hgt);
                    if ($temp_image_slice)
                    {
                        $radians      = $abs_y/$abs_hgt;
                        $degrees      = rad2deg( asin ($radians) );  
                        $this_picture = $this->objects[ $this->turntable[$this->turn_index] ];
                        imagecopyresampled($temp_image_slice, $this_picture, 0, 0, $image_x_pt_top, 0, 1, $abs_hgt, 1, $this->image_height);    
                         
						 
		
                        # "scan" along the vertical line to derive all points along it 
                        for ($point_y=0;$point_y<$abs_hgt;$point_y++)
                        {
                            $this_pt_top = get_offset_from_angle ($point_y, $degrees);
                            $this_y_pt   = $this_y_pt_top + $this_pt_top->y;
                            $this_x_pt   = ($this_y_pt - $this_y_intercept) / $this->left_line->slope;
                            $rgb = imagecolorat($temp_image_slice, 0, $point_y);      
                            if ($this->dither && $point_y<$abs_hgt-1)
                            {
                                # make each "pixel" 2 pixels wide to create dithering effect  
                                imageline($this->frame, $this_x_pt, $this_y_pt, $this_x_pt+2, $this_y_pt, $rgb); 
                            }
                            else
                            {
                                imagesetpixel ($this->frame, $this_x_pt, $this_y_pt, $rgb); 
                            }
                        }  
						
						 /**/
                        imagedestroy ($temp_image_slice);
                    } 
                } 
            }  
            
            if ($this->use_reflection)
            { 
                $plumb_y = $this->plumb_line->abs_y + min($this->plumb_line->y_1, $this->plumb_line->y_2); 
                $offset  = $plumb_y - 1;    
                $alpha   = 1;                       
                for($y=$plumb_y+1;$y<=$this->sy;$y++)
                {               
                    for ($x=0;$x<$this->sx;$x++)    
                    {  
                        $this->reflect_pixel ($x, $offset, $y, $alpha);
                    }       
                                                                                                 
                    $alpha += 2;                                                                                                                     
                    if ($alpha > 100)                                                                                                                              
                    {                                                                                                                              
                        break;                                                                                                                              
                    }          
					$offset--;                                         
                }                                       
            }
        }
		
    } # scan_angled 

# ----------------------------------------------------------------------------
    
	function reflect_pixel ($x, $source_y, $dest_y, $alpha) # reflect_pixel
	{
		$rgb = imagecolorat($this->frame, $x, $source_y);                                                                                                                    
		$tmp = imagecreatetruecolor (1, 1);                                                                                                                                                                                  
		imagesetpixel($tmp, 0, 0, $rgb);                                                                                                                                    
		imagecopymerge($this->frame, $tmp, $x, $dest_y, 0, 0, 1, 1, 100 - $alpha);                                                                                                                                
		imagedestroy ($tmp);  
	} # reflect_pixel

# ----------------------------------------------------------------------------
	
    function increment() # increment
    { 
        $this->save();
        
        $this->height_left   += $this->decrease * $this->right_turn_flag;
        $this->height_right  += $this->decrease * $this->left_turn_flag;
        $this->current_width += $this->decrease * $this->right_turn_flag * 2;
        
        if ($this->current_width<2||$this->current_width>$this->image_width-2)
        {  
            $this->right_turn_flag = -$this->right_turn_flag;
            $this->left_turn_flag  = -$this->left_turn_flag;
            $this->turn_index++; 
        }     
    } # increment

# ----------------------------------------------------------------------------
    
    function generate_workspace() # generate_workspace
    {
        $this->frame                = imagecreatetruecolor ($this->palette_width, $this->palette_height); 
        $this->white                = 0xFFFFFF;  
        $this->black                = 0x000000;  
        $this->blue                 = 0x0000FF;  
        $this->green                = 0x66CC66;  
        $this->red                  = 0xCC0000;  
        $this->gray                 = 0xCCCCCC;  
        $this->ltgreen              = 0xDDDDFF; # imagecolorallocate ($this->frame, 230, 240, 230);
		$this->sx                   = imagesx($this->frame);
        $this->sy                   = imagesy($this->frame); 
		
        $this->palette_y_axis       = $this->sx/2;
        $this->palette_x_axis       = $this->sy/2;        
        $this->img_midpt_right      = $this->height_right/2;
        $this->img_midpt_left       = $this->height_left/2;
        $this->img_midpt_top        = $this->current_width/2;             
        $this->left_top             = ($this->sy - $this->height_left) / 2;
        $this->right_top            = ($this->sy - $this->height_right) / 2;
        $this->top_left             = ($this->sx - $this->current_width) / 2;        
        $this->left_bottom          = $this->left_top + $this->height_left; 
        $this->right_bottom         = $this->right_top + $this->height_right; 
        $this->top_right            = $this->top_left + $this->current_width; 
        
        imagefill($this->frame,0,0,$this->bg_color);         
        
        if ($this->left_turn_flag==-1)
        { # values reversed when image rear showing
            $this->top_left  = $this->sx - $this->top_left;
            $this->top_right = $this->sx - $this->top_right;
        } 
        
        if ($this->angle)
        {
            $this->derive_angled_lines();
        }
        else
        {
            $this->derive_straight_lines();
        }
        
        $this->border = array($this->top_line->x_1, $this->top_line->y_1, 
                        $this->top_line->x_2, $this->top_line->y_2, 
                        $this->bottom_line->x_1, $this->bottom_line->y_1, 
                        $this->bottom_line->x_2, $this->bottom_line->y_2);   
    } # generate_workspace

# ----------------------------------------------------------------------------
    
    function derive_straight_lines() # derive_straight_lines
    {
        $this->top_line    = new ray ($this->top_left, $this->left_top, $this->top_right, $this->right_top);
        $this->bottom_line = new ray ($this->top_right, $this->right_bottom, $this->top_left, $this->left_bottom);    
		
        if ($this->debug)
		{
		    $this->drawgrid();
			
			# upright X and Y axes
			imageline ($this->frame, 0, $this->palette_x_axis, $this->sx, $this->palette_x_axis, $this->gray);  
			imageline ($this->frame, $this->palette_y_axis, $this->sx, $this->palette_y_axis, 0, $this->gray);  
		} 
    } # derive_straight_lines

# ----------------------------------------------------------------------------
    
    function derive_angled_lines() # derive_angled_lines
    {
        /* angle offset of the right line */
        $right_line_angle_offset  = get_offset_from_angle ($this->left_turn_flag==-1 ? $this->img_midpt_left : $this->img_midpt_right, $this->angle); 
        
        /* angle offset of the left line */
        $left_line_angle_offset   = get_offset_from_angle ($this->left_turn_flag==-1 ? $this->img_midpt_right : $this->img_midpt_left, $this->angle); 
        
        $img_x_axis_offset        = get_offset_from_angle ($this->img_midpt_top, $this->angle); /* angle offset of image x-axis  */ 
        $img_x_axis_pt_right      = new point ($this->palette_y_axis + $img_x_axis_offset->x, $this->palette_x_axis - $img_x_axis_offset->y);
        $img_x_axis_pt_left       = new point ($this->palette_y_axis - $img_x_axis_offset->x, $this->palette_x_axis + $img_x_axis_offset->y);        
        
        $y_axis_offset            = get_offset_from_angle ($this->palette_y_axis, $this->angle); /* angle offset of y-axis  */ 
        $y_axis_pt_top            = new point ($this->palette_y_axis - $y_axis_offset->x, $this->palette_x_axis + $y_axis_offset->y);
        $y_axis_pt_bottom         = new point ($this->palette_y_axis + $y_axis_offset->x, $this->palette_x_axis - $y_axis_offset->y);  
        
        $x_axis_offset            = get_offset_from_angle ($this->palette_x_axis, $this->angle); /* angle offset of x-axis  */ 
        $x_axis_pt_top            = new point ($this->palette_y_axis - $x_axis_offset->y, $this->palette_x_axis - $x_axis_offset->x);
        $x_axis_pt_bottom         = new point ($this->palette_y_axis + $x_axis_offset->y, $this->palette_x_axis + $x_axis_offset->x);         
        
        # 4 points of the polygon 
        $img_ne_pt = new point ($img_x_axis_pt_right->x - $right_line_angle_offset->y, $img_x_axis_pt_right->y - $right_line_angle_offset->x);
        $img_se_pt = new point ($img_x_axis_pt_right->x + $right_line_angle_offset->y, $img_x_axis_pt_right->y + $right_line_angle_offset->x); 
        $img_nw_pt = new point ($img_x_axis_pt_left->x - $left_line_angle_offset->y, $img_x_axis_pt_left->y - $left_line_angle_offset->x);
        $img_sw_pt = new point ($img_x_axis_pt_left->x + $left_line_angle_offset->y, $img_x_axis_pt_left->y + $left_line_angle_offset->x);  
          
        # 3 determinant lines      
        $this->top_line      = new ray ($img_nw_pt->x, $img_nw_pt->y, $img_ne_pt->x, $img_ne_pt->y);
        $this->bottom_line   = new ray ($img_se_pt->x, $img_se_pt->y, $img_sw_pt->x, $img_sw_pt->y);
        $this->left_line     = new ray ($img_nw_pt->x, $img_nw_pt->y, $img_sw_pt->x, $img_sw_pt->y);
        $this->right_line    = new ray ($img_ne_pt->x, $img_ne_pt->y, $img_se_pt->x, $img_se_pt->y);
        
		
        if ($this->debug)
		{
		    $this->drawgrid();
			
			# upright X and Y axes
			imageline ($this->frame, 0, $this->palette_x_axis, $this->sx, $this->palette_x_axis, $this->gray);  
			imageline ($this->frame, $this->palette_y_axis, $this->sx, $this->palette_y_axis, 0, $this->gray); 
			
			imageline ($this->frame, $x_axis_pt_top->x, $x_axis_pt_top->y, $x_axis_pt_bottom->x, $x_axis_pt_bottom->y, $this->red);  
			imageline ($this->frame, $y_axis_pt_bottom->x, $y_axis_pt_bottom->y, $y_axis_pt_top->x, $y_axis_pt_top->y, $this->red); 
			
			# tilted X and Y axes
			$axes = array ();
			if ($this->angle < 0)
			{
			    $axes[] = new ray ($x_axis_pt_bottom->x, $x_axis_pt_bottom->y, $x_axis_pt_top->x, $x_axis_pt_top->y);
			    $axes[] = new ray ($y_axis_pt_top->x, $y_axis_pt_top->y, $y_axis_pt_bottom->x, $y_axis_pt_bottom->y);
			}
			else
			{
			    $axes[] = new ray ($x_axis_pt_top->x, $x_axis_pt_top->y, $x_axis_pt_bottom->x, $x_axis_pt_bottom->y);
			    $axes[] = new ray ($y_axis_pt_top->x, $y_axis_pt_top->y, $y_axis_pt_bottom->x, $y_axis_pt_bottom->y);
			}
			
			imagefilledellipse ($this->frame, $y_axis_pt_top->x, $y_axis_pt_top->y, 5, 5, $this->green);
			imagefilledellipse ($this->frame, $x_axis_pt_top->x, $x_axis_pt_top->y, 5, 5, $this->green);
			imagefilledellipse ($this->frame, $y_axis_pt_bottom->x, $y_axis_pt_bottom->y, 5, 5, $this->red);
			imagefilledellipse ($this->frame, $x_axis_pt_bottom->x, $x_axis_pt_bottom->y, 5, 5, $this->red);
			
			for ($i=0;$i<count($axes);$i++)
			{
			    $axis = $axes[$i];
				$hash = get_offset_from_angle (2, $this->angle);
				for ($point_x=20;$point_x<$axis->length;$point_x+=20)
				{
					
					$this_pt_top = get_offset_from_angle ($point_x, $axis->angle);
					$x = $this_pt_top->x + $axis->x_1; # get current X coord   
					$y = ($x * $axis->slope) + $axis->intercept; 
					imagestring ($this->frame,1,$x,$y,$point_x,$this->blue);
					if ($i==0)
					{
					    imageline ($this->frame, floor($x - $hash->x), floor($y + $hash->y), floor($x + $hash->x), floor($y - $hash->y), $this->blue); 
					}
					else
					{ 
					    imageline ($this->frame, floor($x - $hash->x), floor($y - $hash->y), floor($x + $hash->x), floor($y + $hash->y), $this->blue); 
					}
				}
			}
			$arc_w = $this->palette_width-10;
			if ($this->angle > 0)
			{
				imagearc ( $this->frame, $this->palette_x_axis, $this->palette_y_axis, $arc_w, $arc_w, 360-$this->angle, 0, $this->blue ); 
				imagestring ($this->frame, 2, $this->palette_width-75, $this->palette_y_axis-40, $this->angle . " degrees", $this->blue);
			}
			else
			{
				imagearc ( $this->frame, $this->palette_x_axis, $this->palette_y_axis, $arc_w, $arc_w, 0, 0-$this->angle, $this->red ); 
				imagestring ($this->frame, 2, $this->palette_width-75, $this->palette_y_axis+40, $this->angle . " degrees", $this->red);
			}
		}
		
        if ( ! $this->plumb_line)
        {
            $this->plumb_line = $this->angle > 0 ? $this->left_line : $this->right_line; 
        }
    } # derive_angled_lines

# ---------------------------------------------------------------------------- 
    
} # class YAxisRotate  

# ============================================================================ 

class point # class point  
{
    var $x;
    var $y;
    function point ($x=0,$y=0) # point
    {
        $this->x = $x;
        $this->y = $y;
    } # point
}  # class point  

# ============================================================================ 

class ray # class ray  
{
    var $x_1;
    var $x_2;
    var $y_1;
    var $y_2;
    var $slope;
    var $intercept;
    var $length;
    var $angle;
    var $abs_x;
    var $abs_y;
    function ray ($x1,$y1,$x2,$y2) # ray   
    {
        # calculations
        $data    = slope ($x1,$y1,$x2,$y2); 
        $abs_x   = $x2-$x1; 
        $abs_y   = $y2-$y1; 
        $abs_len = sqrt(pow ($abs_x,2) + pow ($abs_y,2));   
        $radians = $abs_y/$abs_len;
        $degrees = rad2deg( asin ($radians) );
         
        # properties
        $this->x_1        = $x1;
        $this->x_2        = $x2;
        $this->y_1        = $y1;
        $this->y_2        = $y2;
        $this->slope      = $data["slope"];
        $this->intercept  = $data["intercept"]; 
        $this->length     = $abs_len;  
        $this->angle      = $degrees; 
        $this->abs_x      = $abs_x; 
        $this->abs_y      = $abs_y;  
    } # ray   
} # class ray  

# ============================================================================ 

# helper functions 
# ----------------------------------------------------------------------------
function slope ($x1,$y1,$x2,$y2) # slope
{
    if ($x1==$x2)
    {
        return array ("slope"=>1,"intercept"=>0);
    }
    $m = ($y1-$y2) / ($x1-$x2);
    $b = $y1 - ($m * $x1);
    return array ("slope"=>$m,"intercept"=>$b);
} # slope 

# ---------------------------------------------------------------------------- 

function get_offset_from_angle ($len,$angle) # get_offset_from_angle
{
    $cos=cos(deg2rad($angle)); 
    $sin=sin(deg2rad($angle));
    $x = $len * $cos; 
    $y = $len * $sin; 
    return new point ($x,$y);
} # get_offset_from_angle



?>
